Improve show_and_select_files() function
authorBenjamin Otte <otte@gnome.org>
Wed, 1 Jul 2009 08:32:26 +0000 (10:32 +0200)
committerBenjamin Otte <otte@gnome.org>
Thu, 15 Oct 2009 20:01:40 +0000 (22:01 +0200)
The previous function enumerated the whole directory and used a lot of
outdated API to decide how to show files.
The new code queries the filesystem model to decide about this.
The now unused old functions were removed.

gtk/gtkfilechooserdefault.c
gtk/gtkfilechooserprivate.h
gtk/gtkfilesystemmodel.c
gtk/gtkfilesystemmodel.h

index 1c7d93c218285c21e15586192df673084648e0e5..dd835e988365a6bb3cf75547c8c7b07b7cce8825 100644 (file)
@@ -369,11 +369,6 @@ static void list_row_activated         (GtkTreeView           *tree_view,
                                        GtkTreeViewColumn     *column,
                                        GtkFileChooserDefault *impl);
 
-static void select_func (GtkFileSystemModel *model,
-                        GtkTreePath        *path,
-                        GtkTreeIter        *iter,
-                        gpointer            user_data);
-
 static void path_bar_clicked (GtkPathBar            *path_bar,
                              GFile                 *file,
                              GFile                 *child,
@@ -5641,12 +5636,6 @@ gtk_file_chooser_default_dispose (GObject *object)
       impl->update_current_folder_cancellable = NULL;
     }
 
-  if (impl->show_and_select_files_cancellable)
-    {
-      g_cancellable_cancel (impl->show_and_select_files_cancellable);
-      impl->show_and_select_files_cancellable = NULL;
-    }
-
   if (impl->should_respond_get_info_cancellable)
     {
       g_cancellable_cancel (impl->should_respond_get_info_cancellable);
@@ -5866,52 +5855,6 @@ gtk_file_chooser_default_size_allocate (GtkWidget     *widget,
   GTK_WIDGET_CLASS (_gtk_file_chooser_default_parent_class)->size_allocate (widget, allocation);
 }
 
-static gboolean
-get_is_file_filtered (GtkFileChooserDefault *impl,
-                     GFile                 *file,
-                     GFileInfo             *file_info)
-{
-  GtkFileFilterInfo filter_info;
-  GtkFileFilterFlags needed;
-  gboolean result;
-
-  if (!impl->current_filter)
-    return FALSE;
-
-  filter_info.contains = GTK_FILE_FILTER_DISPLAY_NAME | GTK_FILE_FILTER_MIME_TYPE;
-
-  needed = gtk_file_filter_get_needed (impl->current_filter);
-
-  filter_info.display_name = g_file_info_get_display_name (file_info);
-  filter_info.mime_type = g_content_type_get_mime_type (g_file_info_get_content_type (file_info));
-
-  if (needed & GTK_FILE_FILTER_FILENAME)
-    {
-      filter_info.filename = g_file_get_path (file);
-      if (filter_info.filename)
-       filter_info.contains |= GTK_FILE_FILTER_FILENAME;
-    }
-  else
-    filter_info.filename = NULL;
-
-  if (needed & GTK_FILE_FILTER_URI)
-    {
-      filter_info.uri = g_file_get_uri (file);
-      if (filter_info.uri)
-       filter_info.contains |= GTK_FILE_FILTER_URI;
-    }
-  else
-    filter_info.uri = NULL;
-
-  result = gtk_file_filter_filter (impl->current_filter, &filter_info);
-
-  g_free ((gchar *)filter_info.filename);
-  g_free ((gchar *)filter_info.uri);
-  g_free ((gchar *)filter_info.mime_type);
-
-  return !result;
-}
-
 static void
 set_sort_column (GtkFileChooserDefault *impl)
 {
@@ -6360,151 +6303,58 @@ browse_files_center_selected_row (GtkFileChooserDefault *impl)
   gtk_tree_selection_selected_foreach (selection, center_selected_row_foreach_cb, &closure);
 }
 
-struct ShowAndSelectPathsData
-{
-  GtkFileChooserDefault *impl;
-  GSList *files;
-};
-
-static void
-show_and_select_files_finished_loading (GtkFolder *folder,
-                                       gpointer   user_data)
+static gboolean
+show_and_select_files (GtkFileChooserDefault *impl,
+                      GSList                *files)
 {
-  gboolean have_hidden;
-  gboolean have_filtered;
-  GSList *l;
-  struct ShowAndSelectPathsData *data = user_data;
-
-  have_hidden = FALSE;
-  have_filtered = FALSE;
-
-  for (l = data->files; l; l = l->next)
-    {
-      GFile *file;
-      GFileInfo *info;
-
-      file = l->data;
-
-      info = _gtk_folder_get_info (folder, file);
-      if (info)
-       {
-         if (!have_hidden)
-           have_hidden = g_file_info_get_is_hidden (info)
-                           || g_file_info_get_is_backup (info);
-
-         if (!have_filtered)
-           have_filtered = (! _gtk_file_info_consider_as_directory (info)) &&
-                            get_is_file_filtered (data->impl, file, info);
-       
-         g_object_unref (info);
-
-         if (have_hidden && have_filtered)
-           break; /* we now have all the information we need */
-       }
-    }
-
-  g_signal_handlers_disconnect_by_func (folder,
-                                       show_and_select_files_finished_loading,
-                                       user_data);
-
-  if (have_hidden)
-    g_object_set (data->impl, "show-hidden", TRUE, NULL);
+  GtkTreeSelection *selection;
+  GtkFileSystemModel *fsmodel;
+  gboolean can_have_hidden, can_have_filtered, selected_a_file;
+  GSList *walk;
 
-  if (have_filtered)
-    set_current_filter (data->impl, NULL);
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
+  fsmodel = GTK_FILE_SYSTEM_MODEL (gtk_tree_view_get_model (GTK_TREE_VIEW (impl->browse_files_tree_view)));
+  can_have_hidden = !impl->show_hidden;
+  can_have_filtered = impl->current_filter != NULL;
+  selected_a_file = FALSE;
 
-  for (l = data->files; l; l = l->next)
+  for (walk = files; walk && (can_have_hidden || can_have_filtered); walk = walk->next)
     {
-      GFile *file;
-      GtkTreePath *path;
+      GFile *file = walk->data;
       GtkTreeIter iter;
 
-      file = l->data;
-      if (!_gtk_file_system_model_get_iter_for_file (data->impl->browse_files_model,
-                                                     &iter,
-                                                     file))
-        return;
-
-      path = gtk_tree_model_get_path (GTK_TREE_MODEL (data->impl->browse_files_model), &iter);
-      select_func (data->impl->browse_files_model, path, &iter, data->impl);
-      gtk_tree_path_free (path);
-    }
-
-  browse_files_center_selected_row (data->impl);
-
-  g_object_unref (data->impl);
-  g_slist_foreach (data->files, (GFunc) g_object_unref, NULL);
-  g_slist_free (data->files);
-  g_free (data);
-}
-
-static void
-show_and_select_files_get_folder_cb (GCancellable *cancellable,
-                                    GtkFolder    *folder,
-                                    const GError *error,
-                                    gpointer      user_data)
-{
-  gboolean cancelled = g_cancellable_is_cancelled (cancellable);
-  struct ShowAndSelectPathsData *data = user_data;
-
-  if (data->impl->show_and_select_files_cancellable != cancellable)
-    goto out;
-
-  data->impl->show_and_select_files_cancellable = NULL;
-
-  if (cancelled || error)
-    goto out;
-
-  g_object_unref (cancellable);
-
-  if (_gtk_folder_is_finished_loading (folder))
-    show_and_select_files_finished_loading (folder, user_data);
-  else
-    g_signal_connect (folder, "finished-loading",
-                     G_CALLBACK (show_and_select_files_finished_loading),
-                     user_data);
-
-  return;
-
-out:
-  g_object_unref (data->impl);
-  g_slist_foreach (data->files, (GFunc) g_object_unref, NULL);
-  g_slist_free (data->files);
-  g_free (data);
-
-  g_object_unref (cancellable);
-}
+      if (!_gtk_file_system_model_get_iter_for_file (fsmodel, &iter, file))
+        continue;
 
-static gboolean
-show_and_select_files (GtkFileChooserDefault *impl,
-                      GFile                 *parent_file,
-                      GSList                *files)
-{
-  struct ShowAndSelectPathsData *info;
+      if (!_gtk_file_system_model_get_is_visible (fsmodel, &iter))
+        {
+          GFileInfo *info = _gtk_file_system_model_get_info (fsmodel, &iter);
 
-  profile_start ("start", NULL);
+          if (can_have_hidden &&
+              (g_file_info_get_is_hidden (info) ||
+               g_file_info_get_is_backup (info)))
+            {
+              g_object_set (impl, "show-hidden", TRUE, NULL);
+              can_have_hidden = FALSE;
+            }
 
-  if (!files)
-    {
-      profile_end ("end", NULL);
-      return TRUE;
+          if (can_have_filtered)
+            {
+              set_current_filter (impl, NULL);
+              can_have_filtered = FALSE;
+            }
+        }
+          
+      if (_gtk_file_system_model_get_is_visible (fsmodel, &iter))
+        {
+          gtk_tree_selection_select_iter (selection, &iter);
+          selected_a_file = TRUE;
+        }
     }
 
-  info = g_new (struct ShowAndSelectPathsData, 1);
-  info->impl = g_object_ref (impl);
-  info->files = g_slist_copy (files);
-  g_slist_foreach (info->files, (GFunc) g_object_ref, NULL);
+  browse_files_center_selected_row (impl);
 
-  if (impl->show_and_select_files_cancellable)
-    g_cancellable_cancel (impl->show_and_select_files_cancellable);
-
-  impl->show_and_select_files_cancellable =
-    _gtk_file_system_get_folder (impl->file_system, parent_file,
-                                "standard::is-hidden,standard::is-backup,standard::type,standard::name,standard::content-type",
-                                show_and_select_files_get_folder_cb, info);
-
-  profile_end ("end", NULL);
-  return TRUE;
+  return selected_a_file;
 }
 
 /* Processes the pending operation when a folder is finished loading */
@@ -6516,7 +6366,7 @@ pending_select_files_process (GtkFileChooserDefault *impl)
 
   if (impl->pending_select_files)
     {
-      show_and_select_files (impl, impl->current_folder, impl->pending_select_files);
+      show_and_select_files (impl, impl->pending_select_files);
       pending_select_files_free (impl);
       browse_files_center_selected_row (impl);
     }
@@ -7380,20 +7230,6 @@ gtk_file_chooser_default_set_current_name (GtkFileChooser *chooser,
   _gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), name);
 }
 
-static void
-select_func (GtkFileSystemModel *model,
-            GtkTreePath        *path,
-            GtkTreeIter        *iter,
-            gpointer            user_data)
-{
-  GtkFileChooserDefault *impl = user_data;
-  GtkTreeSelection *selection;
-
-  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
-
-  gtk_tree_selection_select_iter (selection, iter);
-}
-
 static gboolean
 gtk_file_chooser_default_select_file (GtkFileChooser  *chooser,
                                      GFile           *file,
@@ -7429,7 +7265,7 @@ gtk_file_chooser_default_select_file (GtkFileChooser  *chooser,
       files.data = (gpointer) file;
       files.next = NULL;
 
-      result = show_and_select_files (impl, parent_file, &files);
+      result = show_and_select_files (impl, &files);
       g_object_unref (parent_file);
       return result;
     }
index 933bd86394be52efbf115bee259a295af5f2d2f9..9f02b42e6732aa5a1f8c4f687eb6f03bf00dcb88 100644 (file)
@@ -233,7 +233,6 @@ struct _GtkFileChooserDefault
   GSList *reload_icon_cancellables;
   GCancellable *file_list_drag_data_received_cancellable;
   GCancellable *update_current_folder_cancellable;
-  GCancellable *show_and_select_files_cancellable;
   GCancellable *should_respond_get_info_cancellable;
   GCancellable *file_exists_get_info_cancellable;
   GCancellable *update_from_entry_cancellable;
index 300addf0e57ca136f84c557a77f6565a8a01e853..e2a7c4e54446421df0400441e9b6992a0b2ff058 100644 (file)
@@ -968,11 +968,6 @@ gtk_file_system_model_got_files (GObject *object, GAsyncResult *res, gpointer da
                                      model->cancellable,
                                      gtk_file_system_model_closed_enumerator,
                                      NULL);
-      if (error)
-        g_error_free (error);
-      else
-        g_signal_emit (model, file_system_model_signals[FINISHED_LOADING], 0, NULL);
-
       if (model->dir_thaw_source != 0)
         {
           g_source_remove (model->dir_thaw_source);
@@ -980,6 +975,11 @@ gtk_file_system_model_got_files (GObject *object, GAsyncResult *res, gpointer da
           _gtk_file_system_model_thaw_updates (model);
         }
 
+      if (error)
+        g_error_free (error);
+      else
+        g_signal_emit (model, file_system_model_signals[FINISHED_LOADING], 0, NULL);
+
       g_object_unref (model);
     }
   else
@@ -1315,6 +1315,17 @@ _gtk_file_system_model_set_show_files (GtkFileSystemModel *model,
     }
 }
 
+/**
+ * _gtk_file_system_model_get_cancellable:
+ * @model: the model
+ *
+ * Gets the cancellable used by the @model. This is the cancellable used
+ * internally by the @model that will be cancelled when @model is 
+ * disposed. So you can use it for operations that should be cancelled
+ * when the model goes away.
+ *
+ * Returns: The cancellable used by @model
+ **/
 GCancellable *
 _gtk_file_system_model_get_cancellable (GtkFileSystemModel *model)
 {
@@ -1323,6 +1334,32 @@ _gtk_file_system_model_get_cancellable (GtkFileSystemModel *model)
   return model->cancellable;
 }
 
+/**
+ * _gtk_file_system_model_get_is_visible:
+ * @model: the model
+ * @iter: a valid iterator
+ *
+ * Checks if the iterator is visible. A visible iterator references
+ * a row that is currently exposed using the #GtkTreeModel API. If
+ * the iterator is invisible, it references a file that is not shown
+ * for some reason, such as being filtered by the current filter or
+ * being a hidden file.
+ *
+ * Returns: %TRUE if the iterator is visible
+ **/
+gboolean
+_gtk_file_system_model_get_is_visible (GtkFileSystemModel *model,
+                                      GtkTreeIter        *iter)
+{
+  FileModelNode *node;
+
+  g_return_val_if_fail (GTK_IS_FILE_SYSTEM_MODEL (model), FALSE);
+  g_return_val_if_fail (iter != NULL, FALSE);
+
+  node = get_node (model, ITER_INDEX (iter));
+  return node->visible;
+}
+
 /**
  * _gtk_file_system_model_get_info:
  * @model: a #GtkFileSystemModel
@@ -1347,6 +1384,7 @@ _gtk_file_system_model_get_info (GtkFileSystemModel *model,
   FileModelNode *node;
 
   g_return_val_if_fail (GTK_IS_FILE_SYSTEM_MODEL (model), NULL);
+  g_return_val_if_fail (iter != NULL, NULL);
 
   node = get_node (model, ITER_INDEX (iter));
   g_assert (node->info == NULL || G_IS_FILE_INFO (node->info));
@@ -1447,6 +1485,20 @@ node_get_for_file (GtkFileSystemModel *model,
   return 0;
 }
 
+/**
+ * _gtk_file_system_model_get_iter_for_file:
+ * @model: the model
+ * @iter: the iterator to be initialized
+ * @file: the file to look up
+ *
+ * Initializes @iter to point to the row used for @file, if @file is part 
+ * of the model. Note that upon successful return, @iter may point to an 
+ * invisible row in the @model. Use 
+ * _gtk_file_system_model_get_is_visible() to make sure it is visible to
+ * the tree view.
+ *
+ * Returns: %TRUE if file is part of the model and @iter was initialized
+ **/
 gboolean
 _gtk_file_system_model_get_iter_for_file (GtkFileSystemModel *model,
                                          GtkTreeIter        *iter,
index 0ff4450054b4f97119997672f2927c1f548d59ca..aebc3c8d9cb46dd48f71a2eff57e2be32c818cb3 100644 (file)
@@ -53,6 +53,8 @@ GtkFileSystemModel *_gtk_file_system_model_new_for_directory(GFile *
                                                              guint               n_columns,
                                                              ...);
 GCancellable *      _gtk_file_system_model_get_cancellable  (GtkFileSystemModel *model);
+gboolean            _gtk_file_system_model_get_is_visible   (GtkFileSystemModel *model,
+                                                            GtkTreeIter        *iter);
 GFileInfo *         _gtk_file_system_model_get_info         (GtkFileSystemModel *model,
                                                             GtkTreeIter        *iter);
 gboolean            _gtk_file_system_model_get_iter_for_file(GtkFileSystemModel *model,